`ifndef ISA_SVH
`define ISA_SVH

// GDMA instructions - opcodes 0, 1-3
typedef struct packed {
    logic [71:0] reserved;         // padding to 32 bytes
    logic [15:0] tile_k1;
    logic [15:0] tile_m;
    logic [15:0] start_tensor_k1;
    logic [15:0] start_tensor_m;
    logic [15:0] tensor_k1;
    logic [15:0] tensor_m;
    logic [23:0] ub_addr;          // 3 bytes
    logic [39:0] gm_addr;          // 5 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;           // opcode = 0
} instr_gdma_gm2ub_t;

typedef struct packed {
    logic [79:0] reserved;         // padding to 32 bytes
    logic [15:0] slice_k1;
    logic [15:0] slice_m;
    logic [15:0] start_tensor_k1;
    logic [15:0] start_tensor_m;
    logic [15:0] tensor_k1;
    logic [15:0] tensor_m;
    logic [15:0] lmb_addr;         // 2 bytes
    logic [39:0] gm_addr;          // 5 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;           // opcode = 1
} instr_gdma_gm2lmb_t;

typedef struct packed {
    logic [79:0] reserved;         // padding to 32 bytes
    logic [15:0] slice_k1;
    logic [15:0] slice_n;
    logic [15:0] start_tensor_k1;
    logic [15:0] start_tensor_n;
    logic [15:0] tensor_k1;
    logic [15:0] tensor_n;
    logic [15:0] rmb_addr;         // 2 bytes
    logic [39:0] gm_addr;          // 5 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;           // opcode = 2
} instr_gdma_gm2rmb_t;

typedef struct packed {
    logic [127:0] reserved;        // padding to 32 bytes
    logic [15:0]  slice_n;
    logic [15:0]  start_tensor_n;
    logic [15:0]  tensor_n;
    logic [15:0]  pmb_addr;        // 2 bytes
    logic [39:0]  gm_addr;         // 5 bytes
    logic [15:0]  instr_idx;
    logic [7:0]   opcode;          // opcode = 3
} instr_gdma_gm2pmb_t;

// LDMA instructions - opcodes 16-18
typedef struct packed {
    logic [95:0] reserved;       // padding to 32 bytes
    logic [15:0] slice_k1;
    logic [15:0] slice_m;
    logic [15:0] start_tile_k1;
    logic [15:0] start_tile_m;
    logic [15:0] tile_k1;
    logic [15:0] tile_m;
    logic [15:0] lmb_addr;       // 2 bytes
    logic [23:0] ub_addr;        // 3 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;         // opcode = 16
} instr_ldma_ub2lmb_t;

typedef struct packed {
    logic [95:0] reserved;       // padding to 32 bytes
    logic [15:0] slice_k1;
    logic [15:0] slice_n;
    logic [15:0] start_tile_k1;
    logic [15:0] start_tile_n;
    logic [15:0] tile_k1;
    logic [15:0] tile_n;
    logic [15:0] rmb_addr;       // 2 bytes
    logic [23:0] ub_addr;        // 3 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;         // opcode = 17
} instr_ldma_ub2rmb_t;

typedef struct packed {
    logic [95:0] reserved;       // padding to 32 bytes
    logic [15:0] slice_k1;
    logic [15:0] slice_n;
    logic [15:0] start_tile_k1;
    logic [15:0] start_tile_n;
    logic [15:0] tile_k1;
    logic [15:0] tile_n;
    logic [15:0] rmb_addr;       // 2 bytes
    logic [23:0] ub_addr;        // 3 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;         // opcode = 18
} instr_ldma_ub2rmb_transpose_t;

// MXU instruction - opcode 32
typedef struct packed {
    logic [117:0] reserved;   // padding to 32 bytes
    logic         psum_en;
    logic         bias_en;
    logic [15:0]  slice_k1;
    logic [15:0]  slice_n;
    logic [15:0]  slice_m;
    logic [15:0]  psb_addr;   // 2 bytes
    logic [15:0]  pmb_addr;   // 2 bytes
    logic [15:0]  rmb_addr;   // 2 bytes
    logic [15:0]  lmb_addr;   // 2 bytes
    logic [15:0]  instr_idx;
    logic [7:0]   opcode;     // opcode = 32
} instr_mxu_matmul_t;

// ARU instructions - opcodes 48-52
typedef struct packed {
    logic [15:0] reserved;        // padding to 32 bytes
    logic [1:0]  ub_atomic_mode;
    logic        arb_wr_en;
    logic        ub_wr_en;
    logic [1:0]  reduce_mode;
    logic        reduce_n_en;
    logic        reduce_m_en;
    logic        recp_en;
    logic        pow_en;
    logic        sqrt_en;
    logic        exp_en;
    logic        clamp_en;
    logic        neg_en;
    logic        div_en;
    logic        mul_en;
    logic        min_en;
    logic        max_en;
    logic        sub_en;
    logic        add_en;
    logic        scalar_en;
    logic        br_n;
    logic        br_m;
    logic        arb_en;
    logic [15:0] start_tile_n;
    logic [15:0] start_tile_m;
    logic [15:0] tile_n;
    logic [15:0] tile_m;
    logic [15:0] slice_n;
    logic [15:0] slice_m;
    logic [15:0] clamp_max;       // float16
    logic [15:0] clamp_min;       // float16
    logic [15:0] scalar;          // float16
    logic [7:0]  arb_addr;        // 1 byte
    logic [23:0] ub_addr;         // 3 bytes
    logic [15:0] psb_addr;        // 2 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;          // opcode = 48
} instr_aru_psb2ub_t;

typedef struct packed {
    logic        recp_en;
    logic        pow_en;
    logic        sqrt_en;
    logic        exp_en;
    logic        clamp_en;
    logic        neg_en;
    logic        div_en;
    logic        mul_en;
    logic        min_en;
    logic        max_en;
    logic        sub_en;
    logic        add_en;
    logic        scalar_en;
    logic        br_n;
    logic        br_m;
    logic        arb_en;
    logic [15:0] start_tensor_n;
    logic [15:0] start_tensor_m;
    logic [15:0] tensor_n;
    logic [15:0] tensor_m;
    logic [15:0] slice_n;
    logic [15:0] slice_m;
    logic [15:0] clamp_max;       // float16
    logic [15:0] clamp_min;       // float16
    logic [15:0] scalar;          // float16
    logic [7:0]  arb_addr;        // 1 byte
    logic [39:0] gm_addr;         // 5 bytes
    logic [23:0] psb_addr;        // 3 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;          // opcode = 49
} instr_aru_psb2gm_t;

typedef struct packed {
    logic [31:0] reserved;        // padding to 32 bytes
    logic [1:0]  ub_atomic_mode;
    logic        arb_wr_en;
    logic        ub_wr_en;
    logic [1:0]  reduce_mode;
    logic        reduce_n_en;
    logic        reduce_m_en;
    logic        recp_en;
    logic        pow_en;
    logic        sqrt_en;
    logic        exp_en;
    logic        clamp_en;
    logic        neg_en;
    logic        div_en;
    logic        mul_en;
    logic        min_en;
    logic        max_en;
    logic        sub_en;
    logic        add_en;
    logic        scalar_en;
    logic        br_n;
    logic        br_m;
    logic        arb_en;
    logic [15:0] start_tile_n;
    logic [15:0] start_tile_m;
    logic [15:0] tile_n;
    logic [15:0] tile_m;
    logic [15:0] slice_n;
    logic [15:0] slice_m;
    logic [15:0] clamp_max;       // float16
    logic [15:0] clamp_min;       // float16
    logic [15:0] scalar;          // float16
    logic [7:0]  arb_addr;        // 1 byte
    logic [23:0] ub_addr;         // 3 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;          // opcode = 50
} instr_aru_ub2ub_t;

typedef struct packed {
    logic [32:0] reserved;        // padding to 32 bytes
    logic [1:0]  ub_atomic_mode;
    logic        arb_wr_en;
    logic        ub_wr_en;
    logic [1:0]  reduce_mode;
    logic        reduce_n_en;
    logic        reduce_m_en;
    logic        recp_en;
    logic        pow_en;
    logic        sqrt_en;
    logic        exp_en;
    logic        clamp_en;
    logic        neg_en;
    logic        rsv25;
    logic        min_en;
    logic        max_en;
    logic        sub_en;
    logic        add_en;
    logic        div_en;
    logic        mul_en;
    logic [1:0]  rsv24;
    logic [15:0] start_tile_n;
    logic [15:0] start_tile_m;
    logic [15:0] tile_n;
    logic [15:0] tile_m;
    logic [15:0] slice_n;
    logic [15:0] slice_m;
    logic [15:0] clamp_max;       // float16
    logic [15:0] clamp_min;       // float16
    logic [7:0]  arb_addr;        // 1 byte
    logic [23:0] ub_addr;         // 3 bytes
    logic [15:0] psb_addr;        // 2 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;          // opcode = 51
} instr_aru_dual2ub_t;

typedef struct packed {
    logic        recp_en;
    logic        pow_en;
    logic        sqrt_en;
    logic        exp_en;
    logic        clamp_en;
    logic        neg_en;
    logic        div_en;
    logic        mul_en;
    logic        min_en;
    logic        max_en;
    logic        sub_en;
    logic        add_en;
    logic        scalar_en;
    logic        br_n;
    logic        br_m;
    logic        arb_en;
    logic [15:0] start_tensor_n;
    logic [15:0] start_tensor_m;
    logic [15:0] tensor_n;
    logic [15:0] tensor_m;
    logic [15:0] tile_n;
    logic [15:0] tile_m;
    logic [15:0] clamp_max;       // float16
    logic [15:0] clamp_min;       // float16
    logic [15:0] scalar;          // float16
    logic [7:0]  arb_addr;        // 1 byte
    logic [39:0] gm_addr;         // 5 bytes
    logic [23:0] ub_addr;         // 3 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;          // opcode = 52
} instr_aru_ub2gm_t;

typedef struct packed {
    logic [130:0] reserved;   // padding to 32 bytes
    logic         recp_en;
    logic         pow_en;
    logic         sqrt_en;
    logic         exp_en;
    logic         clamp_en;
    logic         neg_en;
    logic         div_en;
    logic         mul_en;
    logic         min_en;
    logic         max_en;
    logic         sub_en;
    logic         add_en;
    logic         scalar_en;
    logic [15:0]  slice_m;
    logic [15:0]  clamp_max;  // float16
    logic [15:0]  clamp_min;  // float16
    logic [15:0]  scalar;     // float16
    logic [23:0]  arb_addr;   // 3 bytes
    logic [15:0]  instr_idx;
    logic [7:0]   opcode;     // opcode = 53
} instr_aru_arb2arb_t;

// Control instructions - opcodes 64-68
typedef struct packed {
    logic [207:0] reserved; // padding to 32 bytes
    logic [7:0]  id;
    logic [7:0]  dst;
    logic [7:0]  src;
    logic [15:0] instr_idx;
    logic [7:0]  opcode;     // opcode = 64
} instr_set_flag_t;

typedef struct packed {
    logic [207:0] reserved; // padding to 32 bytes
    logic [7:0]  id;
    logic [7:0]  dst;
    logic [7:0]  src;
    logic [15:0] instr_idx;
    logic [7:0]  opcode;     // opcode = 65
} instr_wait_flag_t;

typedef struct packed {
    logic [223:0] reserved; // padding to 32 bytes
    logic [7:0]  eu;
    logic [15:0] instr_idx;
    logic [7:0]  opcode;     // opcode = 66
} instr_fence_t;

typedef struct packed {
    logic [231:0] reserved; // padding to 32 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;     // opcode = 67
} instr_start_t;

typedef struct packed {
    logic [231:0] reserved; // padding to 32 bytes
    logic [15:0] instr_idx;
    logic [7:0]  opcode;     // opcode = 68
} instr_end_t;

// Unified ISA union type
// 报错：Packed union members must have same size.
// Member "end_flag" has different size (24 bits) from next member (256 bits).
// typedef union packed {
//     instr_gdma_gm2ub_t            gdma_gm2ub;
//     instr_gdma_gm2lmb_t           gdma_gm2lmb;
//     instr_gdma_gm2rmb_t           gdma_gm2rmb;
//     instr_gdma_gm2pmb_t           gdma_gm2pmb;
//     instr_ldma_ub2lmb_t           ldma_ub2lmb;
//     instr_ldma_ub2rmb_t           ldma_ub2rmb;
//     instr_ldma_ub2rmb_transpose_t ldma_ub2rmb_transpose;
//     instr_mxu_matmul_t            mxu_matmul;
//     instr_aru_psb2ub_t            aru_psb2ub;
//     instr_aru_psb2gm_t            aru_psb2gm;
//     instr_aru_ub2ub_t             aru_ub2ub;
//     instr_aru_dual2ub_t           aru_dual2ub;
//     instr_aru_ub2gm_t             aru_ub2gm;
//     instr_aru_arb2arb_t           aru_arb2arb;
//     instr_set_flag_t              set_flag;
//     instr_wait_flag_t             wait_flag;
//     instr_fence_t                 fence;
//     instr_start_t                 start_flag;
//     instr_end_t                   end_flag;
//     logic [255:0]                 bin;
// } isa_t;

`endif
